/**
 * Tencent is pleased to support the open source community by making Polaris available.
 *
 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"sort"
	"strconv"
	"strings"
	"text/template"

	api "github.com/polarismesh/polaris/common/api/v1"
)

func main() {
	generateI18nMessageSrc("messages.genearate.go")
	reloadI18nFile("en.toml")
	reloadI18nFile("zh.toml")
}

// reloadI18nFile 根据最新的code 重新刷新i18n文件
func reloadI18nFile(filePath string) {
	list := getSrcCodeInfo()
	existItems := make(map[string]string)
	rfile, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0666)
	if err != nil {
		panic(err)
	}
	defer func() { _ = rfile.Close() }()

	r := bufio.NewReader(rfile)
	for {
		b, _, e := r.ReadLine()
		if e == io.EOF {
			break
		}
		line := string(b)
		existItems[strings.Split(line, " = ")[0]] = line
	}
	wfile, err := os.Create(filePath)
	if err != nil {
		panic(err)
	}
	defer func() { _ = wfile.Close() }()
	w := bufio.NewWriter(wfile)
	for _, item := range list { // 按照err code的大小编码组织
		k := fmt.Sprintf("%d", item.Code)
		line := fmt.Sprintf("%s = \"%s\"    #%s", k, item.Msg, item.Desc)
		if ov, ok := existItems[k]; ok {
			line = ov // 保留文件中的修改
		}
		if _, ierr := fmt.Fprintln(w, line); ierr != nil {
			panic(ierr)
		}
	}
	if ierr := w.Flush(); ierr != nil {
		panic(ierr)
	}
}

func generateI18nMessageSrc(fileName string) {
	var buf bytes.Buffer
	if err := template.Must(template.New("source").Parse(source)).
		Execute(&buf, templateData{ErrCodeList: getSrcCodeInfo()}); err != nil {
		panic(err)
	}
	if err := ioutil.WriteFile(fileName, buf.Bytes(), 0644); err != nil {
		panic(err)
	}
	if err := exec.Command("gofmt", "-w", fileName).Run(); err != nil {
		panic(err)
	}
}

func getSrcCodeInfo() []errCodeItem {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, "../../../common/api/v1/codeinfo.go", nil, parser.ParseComments)
	if err != nil {
		panic(err)
	}
	var list []errCodeItem
	for name, obj := range f.Scope.Objects {
		if obj.Kind.String() != "const" {
			continue
		}
		spec, _ := obj.Decl.(*ast.ValueSpec)
		code, _ := strconv.Atoi(spec.Values[0].(*ast.BasicLit).Value)
		msg := api.Code2Info(uint32(code))
		list = append(list, errCodeItem{
			Code: code,
			Msg:  msg,
			Desc: name, // 变量名作为注释性的描述
		})
	}
	sort.Slice(list, func(i, j int) bool {
		return list[i].Code < list[j].Code
	})
	return list
}

type errCodeItem struct {
	Code int
	Desc string
	Msg  string
}

type templateData struct {
	ErrCodeList []errCodeItem
}

const source = `// Code generated by apiserver/httpserver/i18n/cmd/gen.go; DO NOT EDIT.
/**
 * Tencent is pleased to support the open source community by making Polaris available.
 *
 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package i18n

import (
	"fmt"

	ii18n "github.com/nicksnyder/go-i18n/v2/i18n"
	api "github.com/polarismesh/polaris-server/common/api/v1"
)

func init() {
	i18nMsgCache = map[uint32]*ii18n.Message{
		{{range .ErrCodeList -}}
		api.{{.Desc}}: {ID: fmt.Sprint(api.{{.Desc}})},
		{{end}}
	}
}
`
